package com.info33.platform.config.shiro.realm;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.info33.platform.common.constant.TableConstant;
import com.info33.platform.common.enums.LoginType;
import com.info33.platform.config.shiro.token.UserToken;
import com.info33.platform.system.dao.SysTenantDao;
import com.info33.platform.system.dao.SysTenantMenuDao;
import com.info33.platform.system.dao.SysUserDao;
import com.info33.platform.system.entity.SysTenant;
import com.info33.platform.system.vo.SysUserVO;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.ObjectUtils;

import java.util.List;

/**
 * @author Administrator
 */
public class UserRealm extends AuthorizingRealm {

    @Autowired
    private SysUserDao sysUserDao;
    @Autowired
    private SysTenantDao sysTenantDao;
    @Autowired
    private SysTenantMenuDao sysTenantMenuDao;

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        Object principal = principals.getPrimaryPrincipal();
        SysUserVO user = new SysUserVO();
        BeanUtils.copyProperties(principal, user);
        // 赋权
        List<String> list = sysTenantMenuDao.menuPermission(user);
        if (!ObjectUtils.isEmpty(list)) {
            authorizationInfo.addStringPermissions(list);
        }
        return authorizationInfo;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) {
        UserToken userToken = (UserToken) token;
        SysUserVO sysUserVO;
        // 这里不需要初始化，但避免代码校验报错，进行初始化
        SysTenant sysTenant = new SysTenant();
        // 系统模块，先校验租户信息
        if (userToken.getLoginType().getGroup().equals(LoginType.SYS)) {
            sysTenant = sysTenantDao.selectOne(new QueryWrapper<SysTenant>()
                    .eq("url", userToken.getHost())
                    .last(TableConstant.LIMIT_ONE));
            if (ObjectUtils.isEmpty(sysTenant)) {
                throw new UnknownAccountException(userToken.getHost() + " 租户不存在");
            }
            if (Boolean.FALSE.equals(sysTenant.getActivate())) {
                throw new UnknownAccountException(userToken.getHost() + " 租户未激活，无法登录");
            }
        }
        switch (userToken.getLoginType()) {
            case SYS_PASSWORD:
                sysUserVO = sysUserDao.login(userToken, sysTenant.getId(), 1);
                break;
            case SYS_MESSAGE:
            case SYS_QR_CODE:
                sysUserVO = sysUserDao.login(userToken, sysTenant.getId(), 2);
                break;
            case APP_PASSWORD:
                sysUserVO = sysUserDao.appLogin(userToken, 1);
                break;
            case APP_MESSAGE:
                sysUserVO = sysUserDao.appLogin(userToken, 2);
                break;
            default:
                throw new UnknownAccountException("账号或密码错误，密码输错6次将被锁定");
        }
        // 系统后台登录后的用户验证
        if (userToken.getLoginType().getGroup().equals(LoginType.SYS)) {
            if (ObjectUtils.isEmpty(sysUserVO)) {
                throw new UnknownAccountException("账号或密码错误，密码输错6次将被锁定");
            } else {
                if (Boolean.TRUE.equals(sysUserVO.getSysTenantUserVO().getLocked())) {
                    throw new LockedAccountException();
                }
                sysUserVO.setTenant(sysTenant);
                // 当前用户的主体信息
                return new SimpleAuthenticationInfo(sysUserVO,
                        sysUserVO.getPassword(),
                        ByteSource.Util.bytes(sysUserVO.getSalt()),
                        getName());
            }
        }
        // app 端登录后的租户验证 + 用户验证
        if (userToken.getLoginType().getGroup().equals(LoginType.APP)) {
            if (ObjectUtils.isEmpty(sysUserVO)) {
                throw new UnknownAccountException("账号或密码错误，密码输错6次将被锁定");
            }
            if (Boolean.FALSE.equals(sysUserVO.getTenant().getActivate())) {
                throw new UnknownAccountException(userToken.getHost() + " 租户未激活，无法登录");
            }
            if (Boolean.FALSE.equals(sysUserVO.getTenant().getHasApp())) {
                throw new UnknownAccountException("此租户 app 应用已经下架，无法登录");
            }
            if (Boolean.TRUE.equals(sysUserVO.getAppTenantUserVO().getLocked())) {
                throw new LockedAccountException();
            }
            return new SimpleAuthenticationInfo(sysUserVO,
                    sysUserVO.getPassword(),
                    ByteSource.Util.bytes(sysUserVO.getSalt()),
                    getName());
        }
        throw new AuthenticationException();
    }

}
